;; Author: Torsten Stüber

;; input/output pointer $p: 16 i64 = 128 bytes
;; input/output pointer $q: 16 i64 = 128 bytes
;; input value $b (is 1 or 0)
(func $sel25519 (export "sel25519")
	(param $p i32)
	(param $q i32)
	(param $b i32)

	(local $t i64)
	(local $c i64)

	(set_local $c (i64.xor (i64.sub (i64.extend_u/i32 (get_local $b)) (i64.const 1)) (i64.const -1)))
	
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=0 (get_local $p)) (i64.load offset=0 (get_local $q)))))
	(i64.store offset=0 (get_local $p) (i64.xor (i64.load offset=0 (get_local $p)) (get_local $t)))
	(i64.store offset=0 (get_local $q) (i64.xor (i64.load offset=0 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=8 (get_local $p)) (i64.load offset=8 (get_local $q)))))
	(i64.store offset=8 (get_local $p) (i64.xor (i64.load offset=8 (get_local $p)) (get_local $t)))
	(i64.store offset=8 (get_local $q) (i64.xor (i64.load offset=8 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=16 (get_local $p)) (i64.load offset=16 (get_local $q)))))
	(i64.store offset=16 (get_local $p) (i64.xor (i64.load offset=16 (get_local $p)) (get_local $t)))
	(i64.store offset=16 (get_local $q) (i64.xor (i64.load offset=16 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=24 (get_local $p)) (i64.load offset=24 (get_local $q)))))
	(i64.store offset=24 (get_local $p) (i64.xor (i64.load offset=24 (get_local $p)) (get_local $t)))
	(i64.store offset=24 (get_local $q) (i64.xor (i64.load offset=24 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=32 (get_local $p)) (i64.load offset=32 (get_local $q)))))
	(i64.store offset=32 (get_local $p) (i64.xor (i64.load offset=32 (get_local $p)) (get_local $t)))
	(i64.store offset=32 (get_local $q) (i64.xor (i64.load offset=32 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=40 (get_local $p)) (i64.load offset=40 (get_local $q)))))
	(i64.store offset=40 (get_local $p) (i64.xor (i64.load offset=40 (get_local $p)) (get_local $t)))
	(i64.store offset=40 (get_local $q) (i64.xor (i64.load offset=40 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=48 (get_local $p)) (i64.load offset=48 (get_local $q)))))
	(i64.store offset=48 (get_local $p) (i64.xor (i64.load offset=48 (get_local $p)) (get_local $t)))
	(i64.store offset=48 (get_local $q) (i64.xor (i64.load offset=48 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=56 (get_local $p)) (i64.load offset=56 (get_local $q)))))
	(i64.store offset=56 (get_local $p) (i64.xor (i64.load offset=56 (get_local $p)) (get_local $t)))
	(i64.store offset=56 (get_local $q) (i64.xor (i64.load offset=56 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=64 (get_local $p)) (i64.load offset=64 (get_local $q)))))
	(i64.store offset=64 (get_local $p) (i64.xor (i64.load offset=64 (get_local $p)) (get_local $t)))
	(i64.store offset=64 (get_local $q) (i64.xor (i64.load offset=64 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=72 (get_local $p)) (i64.load offset=72 (get_local $q)))))
	(i64.store offset=72 (get_local $p) (i64.xor (i64.load offset=72 (get_local $p)) (get_local $t)))
	(i64.store offset=72 (get_local $q) (i64.xor (i64.load offset=72 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=80 (get_local $p)) (i64.load offset=80 (get_local $q)))))
	(i64.store offset=80 (get_local $p) (i64.xor (i64.load offset=80 (get_local $p)) (get_local $t)))
	(i64.store offset=80 (get_local $q) (i64.xor (i64.load offset=80 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=88 (get_local $p)) (i64.load offset=88 (get_local $q)))))
	(i64.store offset=88 (get_local $p) (i64.xor (i64.load offset=88 (get_local $p)) (get_local $t)))
	(i64.store offset=88 (get_local $q) (i64.xor (i64.load offset=88 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=96 (get_local $p)) (i64.load offset=96 (get_local $q)))))
	(i64.store offset=96 (get_local $p) (i64.xor (i64.load offset=96 (get_local $p)) (get_local $t)))
	(i64.store offset=96 (get_local $q) (i64.xor (i64.load offset=96 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=104 (get_local $p)) (i64.load offset=104 (get_local $q)))))
	(i64.store offset=104 (get_local $p) (i64.xor (i64.load offset=104 (get_local $p)) (get_local $t)))
	(i64.store offset=104 (get_local $q) (i64.xor (i64.load offset=104 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=112 (get_local $p)) (i64.load offset=112 (get_local $q)))))
	(i64.store offset=112 (get_local $p) (i64.xor (i64.load offset=112 (get_local $p)) (get_local $t)))
	(i64.store offset=112 (get_local $q) (i64.xor (i64.load offset=112 (get_local $q)) (get_local $t)))
	(set_local $t (i64.and (get_local $c) (i64.xor (i64.load offset=120 (get_local $p)) (i64.load offset=120 (get_local $q)))))
	(i64.store offset=120 (get_local $p) (i64.xor (i64.load offset=120 (get_local $p)) (get_local $t)))
	(i64.store offset=120 (get_local $q) (i64.xor (i64.load offset=120 (get_local $q)) (get_local $t)))
)